package com.sy.core.shiro;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    //配置自定义的Realm
    @Bean
    public MmsRealm getRealm() {
        return new MmsRealm();
    }

    //配置安全管理器
    @Bean
    public SecurityManager securityManager(MmsRealm realm) {
        //使用默认的安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
        // 自定义session管理 使用redis
        securityManager.setSessionManager(sessionManager());
        // 自定义缓存实现 使用redis
        securityManager.setCacheManager(cacheManager());
        //将自定义的realm交给安全管理器统一调度管理
        securityManager.setRealm(realm);
        return securityManager;
    }

    //Filter工厂，设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        //1.创建shiro过滤器工厂
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        //2.设置安全管理器
        filterFactory.setSecurityManager(securityManager);
        //3.通用配置（配置登录页面，登录成功页面，验证未成功页面）
        filterFactory.setLoginUrl("/autherror/error?code=1"); //设置登录页面
        //filterFactory.setUnauthorizedUrl("/autherror/error?code=2"); //授权失败跳转页面
        //4.配置过滤器集合
        /**
         * key  ：访问连接
         *      支持通配符的形式
         * value：过滤器类型
         *      shiro常用过滤器
         *          anno    ：匿名访问（表明此链接所有人可以访问）
         *          authc   ：认证后访问（表明此链接需登录认证成功之后可以访问）
         */
        Map<String,String> filterMap = new LinkedHashMap<String,String>();
        //配置请求连接过滤器配置
        //匿名访问（所有人员可以使用）
        filterMap.put("/login/login_in", "anon");
        filterMap.put("/autherror/error", "anon");
        filterMap.put("/swagger-ui.html", "anon");
        filterMap.put("/**/css/**", "anon");
        filterMap.put("/webjars/springfox-swagger-ui/**", "anon");
        filterMap.put("/swagger-resources", "anon");
        filterMap.put("/configuration/**", "anon");
        filterMap.put("/error", "anon");
        filterMap.put("/sysUser/export","anon");
        filterMap.put("/sysUser/exportPdf","anon");
        //filterMap.put("/logout","logout");//退出登录，shiro自带会清楚各种缓存
        //具有指定权限访问
        //filterMap.put("/user/find", "perms[user-find]");
        //认证之后访问（登录之后可以访问）
        filterMap.put("/**", "authc");
        //具有指定角色可以访问
        //filterMap.put("/user/**", "roles[系统管理员]");


        //5.设置过滤器
        filterFactory.setFilterChainDefinitionMap(filterMap);
        return filterFactory;
    }

    //配置shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    //配置shiro redisManager
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;
    }

    //cacheManager缓存 redis实现
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    /**
     * RedisSessionDAO shiro sessionDao层的实现 通过redis
     * 使用的是shiro-redis开源插件
     */
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setExpire(60*60*24*15);
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }

    /**
     * shiro session的管理
     */
    public DefaultWebSessionManager sessionManager() {
        //DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        MmsWebSessionManager mmsWebSessionManager = new MmsWebSessionManager();
        mmsWebSessionManager.setSessionDAO(redisSessionDAO());
        mmsWebSessionManager.setSessionIdUrlRewritingEnabled(true);
        mmsWebSessionManager.setGlobalSessionTimeout(1000*60*60*24*15);
        //Cookie cookie =  sessionManager.getSessionIdCookie();
        //cookie.setName("my_sid"); //声明cooike中session的名称
        //sessionManager.setSessionIdCookie(cookie);
        return mmsWebSessionManager;
    }

    /**
     * 注入自己的MmsWebSessionManager
     */
   /* @Bean
    public MmsWebSessionManager getMmsWebSessionManager(){
        MmsWebSessionManager mmsWebSessionManager = new MmsWebSessionManager();
        return mmsWebSessionManager;
    }*/
}
